<script>
  const Actions = (h, vm, option = {}) => {
    if (!vm.isDrag) {
      return
    }

    if (!vm.item['_custom_active']) {
      return
    }
    return h('div', {
      class: {
        'formItem-actions': true
      }
    }, [
      Top(h, vm, option),
      Bottom(h, vm, option),
      Delete(h, vm, option),
      LeftChange(h, vm, option),
      RightChange(h, vm, option)
    ])
  }

  const Top = (h, vm, option = {}) => {
    if (
      vm.parentIndex === 0 ||
      vm.formData[vm.parentIndex - 1].children.length >= 4
    ) {
      return
    }
    return h('div', {
      class: {
        'formItem-top': true
      },
      on: {
        click: vm.topClick
      }
    }, [
      h('Icon', {
        props: {
          type: 'arrow-up-c',
          color: '#008cee'
        }
      })
    ])
  }

  const Bottom = (h, vm, option = {}) => {
    if (vm.formData[vm.parentIndex].children.length <= 1) {
      return
    }
    return h('div', {
      class: {
        'formItem-bottom': true
      },
      on: {
        click: vm.bottomClick
      }
    }, [
      h('Icon', {
        props: {
          type: 'arrow-down-c',
          color: '#008cee'
        }
      })
    ])
  }

  const Delete = (h, vm, option = {}) => {
    return h('div', {
      class: {
        'formItem-delete': true
      },
      on: {
        click: vm.deleteClick
      }
    }, [
      h('Icon', {
        props: {
          type: 'trash-a',
          color: '#ff6600'
        }
      })
    ])
  }

  const LeftChange = (h, vm, option = {}) => {
    if (vm.formData[vm.parentIndex].children[vm.index - 1] === undefined) {
      return
    }
    return h('div', {
      class: {
        'formItem-leftChange': true
      },
      on: {
        click: vm.leftChangeClick
      }
    }, [
      h('Icon', {
        props: {
          type: 'arrow-swap',
          color: '#19be6b'
        }
      })
    ])
  }

  const RightChange = (h, vm, option = {}) => {
    if (vm.formData[vm.parentIndex].children[vm.index + 1] === undefined) {
      return
    }
    return h('div', {
      class: {
        'formItem-rightChange': true
      },
      on: {
        click: vm.rightChangeClick
      }
    }, [
      h('Icon', {
        props: {
          type: 'arrow-swap',
          color: '#19be6b'
        }
      })
    ])
  }

  const FormItem = (h, vm, option = {}) => {
    let mask = null

    if (vm.isDrag) {
      mask = h('div', {
        class: {
          'formItem-mask': true
        }
      })
    }

    if (
      vm.item.options !== undefined &&
      typeof vm.item.options === 'object'
    ) {
      const { value } = vm.item.options
      if (value !== undefined) {
        vm.contentChange(vm.item['id'], value)
      }
    }

    const props = {}
    let content = []

    if (!vm.isDrag) {
      props.label = vm.item.label
      content = option.els
    } else {
      content.push(
        h('div', {
          class: {
            'drag-label': true
          }
        }, [h('div', {
          class: {
            'drag-label-content': vm.item.isRequired
          }
        }, vm.item.label)])
      )
      content.push(
        h('div', {
          class: {
            'drag-content': true
          }
        }, option.els)
      )
    }

    if (
      !vm.isDrag &&
      vm.item.isRequired
    ) {
      props['prop'] = vm.item['id']
    }

    return h('FormItem', {
      class: {
        'formItem-container': true,
        'active': vm.item['_custom_active']
      },
      props,
      nativeOn: {
        'click': vm.formItemClick
      }
    }, [
      h('div', {
        class: {
          'formItem-content': true
        }
      }, content),
      mask,
      Actions(h, vm, option)
    ])
  }

  const Input = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Input', {
          props: vm.item.options,
          style: vm.item.styles,
          on: {
            'on-change': event => {
              const { value } = event.target
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        })
      ]
    })
  }

  const Textarea = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Input', {
          props: {
            type: 'textarea',
            ...vm.item.options
          },
          style: vm.item.styles,
          on: {
            'on-change': event => {
              const { value } = event.target
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        })
      ]
    })
  }

  const InputNumber = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('InputNumber', {
          props: vm.item.options,
          style: vm.item.styles,
          on: {
            'on-change': value => {
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
              if (vm.item.operationParent !== undefined) {
                vm.item.operationParent.map(item => {
                  vm.formData.map(child1 => {
                    child1.children.map(child2 => {
                      if (child2.id === item) {
                        vm.$emit('refreshOperation', child2)
                        // console.log(vm.$parent.$parent)
                        // const str = vm.$parent._Operation(child2.operation.value)
                        // const num = vm.$parent.evil(str)

                        // vm.$set(child2.options, 'value', num)
                        // vm.$parent.formObj[child2.id] = num
                      }
                    })
                  })
                })
              }
            }
          }
        })
      ]
    })
  }

  const Select = (h, vm, option = {}) => {
    const optionArr = []
    const { optionList } = vm.item

    if (Array.isArray(optionList)) {
      optionList.map((child, childIndex) => {
        optionArr.push(
          h('Option', {
            props: {
              key: childIndex,
              ...child
            }
          }, child.label)
        )
      })
    }

    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Select', {
          props: vm.item.options,
          style: vm.item.styles,
          on: {
            'on-change': value => {
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        }, optionArr)
      ]
    })
  }

  const Upload = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Upload', {
          props: vm.item.options,
          style: vm.item.styles
        }, [
          h('Button', {
            props: {
              type: 'ghost',
              icon: 'ios-cloud-upload-outline'
            }
          }, '上传')
        ])
      ]
    })
  }

  const DatePicker = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('DatePicker', {
          props: vm.item.options,
          style: vm.item.styles,
          on: {
            'on-change': value => {
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        })
      ]
    })
  }

  const Checkbox = (h, vm, option = {}) => {
    let checkboxArr = []
    const { checkboxList } = vm.item

    checkboxList.map(child => {
      checkboxArr.push(
        h('Checkbox', {
          props: child,
          style: vm.item.styles,
          on: {
            'on-change': value => {
              if (child.value === undefined) {
                vm.$set(child, 'value', value)
              } else {
                child.value = value
              }
            }
          }
        }, child.label)
      )
    })

    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        ...checkboxArr
      ]
    })
  }

  const CheckboxGroup = (h, vm, option = {}) => {
    let checkboxArr = []
    const { checkboxList } = vm.item

    checkboxList.map(child => {
      checkboxArr.push(
        h('Checkbox', {
          props: child,
          style: vm.item.styles
        })
      )
    })

    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('CheckboxGroup', {
          props: {
            ...vm.item.options
          },
          on: {
            'on-change': value => {
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        }, checkboxArr)
      ]
    })
  }

  const Radio = (h, vm, option = {}) => {
    let radioArr = []
    const { radioList } = vm.item

    radioList.map(child => {
      radioArr.push(
        h('Radio', {
          props: child,
          style: vm.item.styles,
          on: {
            'on-change': value => {
              if (child.value === undefined) {
                vm.$set(child, 'value', value)
              } else {
                child.value = value
              }
            }
          }
        }, child.label)
      )
    })

    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        ...radioArr
      ]
    })
  }

  const RadioGroup = (h, vm, option = {}) => {
    let radioArr = []
    const { radioList } = vm.item

    radioList.map(child => {
      radioArr.push(
        h('Radio', {
          props: child,
          style: vm.item.styles
        })
      )
    })

    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('RadioGroup', {
          props: {
            ...vm.item.options
          },
          on: {
            'on-change': value => {
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        }, radioArr)
      ]
    })
  }

  const Table = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Table', {
          props: vm.item.options,
          style: vm.item.styles
        })
      ]
    })
  }

  const CellInput = (h, vm, params = {}, column = {}) => {
    const { index } = params
    const { key } = column

    return h('Input', {
      props: {
        value: vm.edittingStore[index][key]
      },
      nativeOn: {
        'click': event => {
          vm.CancelBubble(event)
        }
      },
      on: {
        'on-change': event => {
          const { value } = event.target

          vm.edittingStore[index][key] = value
          vm.tableValueChange(index, key, value)
        }
      }
    })
  }

  const CellInputNumber = (h, vm, params = {}, column = {}) => {
    const { index } = params
    const { key } = column

    return h('InputNumber', {
      props: {
        value: vm.edittingStore[index][key]
      },
      nativeOn: {
        'click': event => {
          vm.CancelBubble(event)
        }
      },
      on: {
        'on-change': value => {
          vm.edittingStore[index][key] = value
          vm.tableValueChange(index, key, value)
        }
      }
    })
  }

  const CellCheckboxGroup = (h, vm, params = {}, column = {}) => {
    const checkboxArr = []
    const { index } = params
    const { key, checkboxList } = column

    checkboxList.map(child => {
      const { label } = child
      checkboxArr.push(
        h('Checkbox', {
          props: {
            value: vm.edittingStore[index][key].indexOf(label) > -1
          },
          nativeOn: {
            'click': event => {
              vm.CancelBubble(event)
            }
          },
          on: {
            'on-change': value => {
              if (value) {
                vm.edittingStore[index][key].push(label)
              } else {
                const childIndex = vm.edittingStore[index][key].findIndex(labelItem => labelItem === label)
                vm.edittingStore[index][key].splice(childIndex, 1)
              }
              vm.tableValueChange(index, key, vm.edittingStore[index][key])
            }
          }
        }, child.label)
      )
    })

    return h('div', {}, checkboxArr)
  }

  const EditTable = (h, vm, data = {}) => {
    const thead = []
    vm.item.options.columns.map(column => {
      switch (column.type) {
        case 'Input':
          thead.push({
            ...column,
            render: (tableCreateEl, params) => {
              return CellInput(tableCreateEl, vm, params, column)
            }
          })
          break
        case 'InputNumber':
          thead.push({
            ...column,
            render: (tableCreateEl, params) => {
              return CellInputNumber(tableCreateEl, vm, params, column)
            }
          })
          break
        case 'CheckboxGroup':
          thead.push({
            ...column,
            render: (tableCreateEl, params) => {
              return CellCheckboxGroup(tableCreateEl, vm, params, column)
            }
          })
          break
      }
    })

    return FormItem(h, vm, {
      els: [
        h('Table', {
          props: {
            columns: thead,
            data: vm.edittingStore
          },
          style: vm.item.styles
        }),
        h('Button', {
          on: {
            'click': () => {
              vm.addTbody()
            }
          }
        }, '增加一行')
      ]
    })
  }

  const Operation = (h, vm, option = {}) => {
    return FormItem(h, vm, {
      els: [
        // h('div', {}, vm.item.label),
        h('Input', {
          props: {
            number: true,
            readonly: true,
            ...vm.item.options
          },
          style: vm.item.styles,
          on: {
            'on-change': event => {
              const { value } = event.target
              if (vm.item.options.value === undefined) {
                vm.$set(vm.item.options, 'value', value)
              } else {
                vm.item.options.value = value
              }
              if (vm.item.isRequired) {
                vm.contentChange(vm.item['id'], value)
              }
            }
          }
        })
      ]
    })
  }

  export default {
    props: {
      isDrag: {
        type: Boolean,
        default: true
      },
      formData: {
        type: Array,
        default: () => []
      },
      parentIndex: {
        type: Number,
        default: 0
      },
      item: {
        type: Object,
        default: () => ({})
      },
      index: {
        type: Number,
        default: 0
      }
    },
    computed: {
      tbodyData () {
        if (this.item.type === 'EditTable') {
          return this.item.options.data
        }

        return undefined
      }
    },
    watch: {
      tbodyData (newTbody) {
        this.editTableInit()
        this.$forceUpdate()
      }
    },
    created () {
      this.editTableInit()
    },
    data () {
      return {
        // edittingStore: []
      }
    },
    methods: {
      addTbody () {
        this.item.options.data.push({
          name: 'Joe Black',
          age: 30,
          address: ['Sydney'],
          date: '2016-10-02'
        })
      },
      editTableInit () {
        if (this.item.type === 'EditTable') {
          this.edittingStore = JSON.parse(JSON.stringify(this.tbodyData))
        }
      },
      tableValueChange (index, key, value) {
        this.$emit('tableValueChange', { id: this.item.id, index, key, value })
      },
      contentChange (key, val) {
        this.$emit('input', val)
        this.$emit('contentChange')
      },
      topClick (e) {
        this.$emit('topClick')
        this.CancelBubble(e)
      },
      bottomClick (e) {
        this.$emit('bottomClick')
        this.CancelBubble(e)
      },
      deleteClick (e) {
        this.$emit('deleteClick')
        this.CancelBubble(e)
      },
      leftChangeClick (e) {
        this.$emit('leftChangeClick')
        this.CancelBubble(e)
      },
      rightChangeClick (e) {
        this.$emit('rightChangeClick')
        this.CancelBubble(e)
      },
      formItemClick () {
        this.$emit('formItemClick')
      },
      CancelBubble (event) {
        if (event.stopPropagation) {
          event.stopPropagation()
        } else {
          event.cancelBubble = true
        }
      }
    },
    render (h) {
      const { type } = this.item
      if (type === 'Textarea') {
        return Textarea(h, this)
      } else if (type === 'InputNumber') {
        return InputNumber(h, this)
      } else if (type === 'Select') {
        return Select(h, this)
      } else if (type === 'Upload') {
        return Upload(h, this)
      } else if (type === 'DatePicker') {
        return DatePicker(h, this)
      } else if (type === 'Checkbox') {
        return Checkbox(h, this)
      } else if (type === 'CheckboxGroup') {
        return CheckboxGroup(h, this)
      } else if (type === 'Radio') {
        return Radio(h, this)
      } else if (type === 'RadioGroup') {
        return RadioGroup(h, this)
      } else if (type === 'Table') {
        return Table(h, this)
      } else if (type === 'EditTable') {
        return EditTable(h, this)
      } else if (type === 'Operation') {
        return Operation(h, this)
      } else {
        return Input(h, this)
      }
    }
  }
</script>

<style lang="scss">
  .formItem-container {
    position: relative;
    user-select: none;
    margin: 0;
    padding: 20px;
    flex: 1;
    border-right: 1px solid lightgray;
    box-sizing: border-box;
    &:nth-last-of-type(1) {
      border-right: none;
    }
    &:hover {
      background-color: #fafafb;
    }
    &.active {
      background-color: rgb(244, 244, 255);
    }
    .ivu-form-item-content {
      width: 100%;
      height: 100%;
      position: initial;
      .ivu-form-item-error-tip {
        left: auto;
        top: auto;
      }
    }
    .formItem-content {
      // position: relative;
      // z-index: 4;
      // display: flex;
      > .drag-label {
        // line-height: 1;
        // padding-bottom: 10px;
        // padding: 10px 12px 10px 0;
        > .drag-label-content {
          &::before {
            content: '*';
            display: inline-block;
            margin-right: 4px;
            line-height: 1;
            font-family: SimSun;
            font-size: 12px;
            color: #ed3f14;
          }
        }
      }
      // > .drag-content {
      //   flex: 1;
      //   position: relative;
      // }
    }
    .formItem-mask {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      overflow: hidden;
      z-index: 2;
    }
    .formItem-actions {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      z-index: 2;
      .formItem-top {
        width: 16px;
        height: 16px;
        border-radius: 50%;
        background-color: white;
        position: absolute;
        left: 0;
        right: 0;
        top: -8px;
        margin: 0 auto;
        cursor: pointer;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .formItem-bottom {
        width: 16px;
        height: 16px;
        text-align: center;
        border-radius: 50%;
        background-color: white;
        position: absolute;
        left: 0;
        right: 0;
        bottom: -8px;
        margin: 0 auto;
        cursor: pointer;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .formItem-delete {
        width: 16px;
        height: 16px;
        text-align: center;
        border-radius: 50%;
        background-color: white;
        position: absolute;
        top: -8px;
        right: -8px;
        cursor: pointer;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .formItem-leftChange {
        width: 16px;
        height: 16px;
        text-align: center;
        border-radius: 50%;
        background-color: white;
        position: absolute;
        top: 0;
        bottom: 0;
        left: -8px;
        margin: auto 0;
        cursor: pointer;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .formItem-rightChange {
        width: 16px;
        height: 16px;
        text-align: center;
        border-radius: 50%;
        background-color: white;
        position: absolute;
        top: 0;
        bottom: 0;
        right: -8px;
        margin: auto 0;
        cursor: pointer;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }

</style>

